﻿using System;
using System.Collections.Generic;
using System.Threading;
using SportTraining.Core.Services;
using TermClasses;

namespace SportTraining.Services
{
    public class BillAcceptor : IBillAcceptor
    {

        #region private var
        private readonly ITerminalBillValidator billValidator;
        private bool internalBreakOperation;
        private Thread waitMoneyThread;
        private int feeAmount;
        #endregion

        #region constr
        public BillAcceptor(ITerminalBillValidator billValidator)
        {
            this.billValidator = billValidator;

            this.billValidator.Initialize();
        }
        #endregion

        #region Implementation of IBillAcceptor
        public IList<int> GetAcceptableBillDenominations()
        {
            try
            {
                return billValidator.GetAcceptableBillDenominations();
            }
            catch (Exception e)
            {

                //logger.Error(e.Message, e);
                throw new TerminalDeviceException("Ошибка получения списка разрешённых для ввода значений денежных номиналов.", e);
            }
        }

        public void StartWaitMoney()
        {
            feeAmount = 0;
            internalBreakOperation = false;
            waitMoneyThread = new Thread(WaitMoneyMethod) { Name = "WaitMoneyThread" };
            waitMoneyThread.Start();
        }

        public void StopWaitMoney()
        {
            ReceiveMoneyEvent = null;
            internalBreakOperation = true;
        }

        public event EventHandler<BillAcceptorEventArgs> ReceiveMoneyEvent;
        public event EventHandler<TerminalDeviceErrorEventArgs> ErrorEvent;

        public bool IsPendingMoney
        {
            get { return !internalBreakOperation; }
        }

        private void WaitMoneyMethod()
        {
            try
            {
                do
                {
                    feeAmount = billValidator.AcceptMoneyInterruptable(ref internalBreakOperation);

                    if (feeAmount > 0 && ReceiveMoneyEvent != null)
                    {
                        ReceiveMoneyEvent(this, new BillAcceptorEventArgs { ReceiveMoney  = feeAmount});
                    }
                }
                while (!internalBreakOperation);
            }
            catch (Exception e)
            {
                //logger.Error(e.Message, e);

                if (ErrorEvent != null)
                {
                    ErrorEvent(this, new TerminalDeviceErrorEventArgs{TerminalDeviceException = e});
                }
            }
        }
        #endregion
    }
}

